import Vue from 'vue';
import componentFactory from 'vue-class-component';

export default function (options: DefineOptions): <V extends ({ new (): Vue } & typeof Vue) >(target: V) => V {

    return function (target) {

        let defineDescriptor = [];

        if (options.define || options.name) {
            defineDescriptor.push(options.define || options.name);
            delete options.define;
        }

        let depends: any[] = [];
        if (options.components) {
            for (let key in options.components) {
                if (typeof options.components[key] === 'string') {
                    depends.push(options.components[key]);
                    options.components[key] = depends.length;
                }
            }
        }

        if (depends.length) {
            defineDescriptor.push(depends, (...args) => {
                for (let key in options.components) {
                    if (typeof options.components[key] === 'number') {
                        options.components[key] = args[options.components[key] as number];
                    }
                }
                return componentFactory(options)(target);
            });
        } else {
            if (!!defineDescriptor.length) {
                defineDescriptor.push(() => componentFactory(options)(target));
            } else {
                return componentFactory(options)(target);
            }
        }
        return Midware.componentDefine.apply(Midware, defineDescriptor);

    };
}


interface DefineOptions extends Vue.ComponentOptions<Vue> {
    define?: string
    components?: {
        [key: string]: string | Vue.Component | Vue.AsyncComponent
    }
}
